/**
 * 单行 item 数量
 */
const LineCount = 9

/**
 * 开始倒计时 s
 */
const SatrtCountdownSecond = 3

/**
 * 游戏状态
 */
enum GAME_STATUS {
    INIT,
    RUNNING,
    END,
}

/**
 * Mahjong 信息
 */
const Mahjong = {
    /**
     * 类型: 万 筒 索
     */
    Type: ['w', 't', 's'],
    /**
     * 类型牌张数
     */
    SingleCount: 9,
    /**
     * 有几张一样的牌
     */
    SingleRepeat: 4,
    /**
     * 总共牌数
     */
    TotalCount: 108,
}

/**
 * 游戏数据
 */
class GameInfo {
    status: GAME_STATUS
    cardScale: number
    data: Array<string>
    selectCards: Array<cc.Node>
    playing: boolean
    totalTime: number
}

const { ccclass, property } = cc._decorator;
@ccclass
export default class Game extends cc.Component {

    @property(cc.Node)
    cardsContent: cc.Node = null

    @property(cc.Node)
    cardItem: cc.Node = null

    @property(cc.Node)
    winParticle: cc.Node = null

    @property(cc.Node)
    startCountdown: cc.Node = null

    @property(cc.Node)
    timer: cc.Node = null

    _gameInfo: GameInfo
    tt: any
    onLoad() {

        //@ts-ignore
        window.aaa = this

        this.tt = () => { this.timer.getComponent(cc.Label).string = `${this._gameInfo.totalTime++}s` }

        this._gameInfo = new GameInfo()

        // 计算 cardItem 比例
        this._gameInfo.cardScale = Math.floor((this.cardsContent.width / LineCount) / this.cardItem.width * 100) / 100

        this._gameInfo.data = []

        // 创建 cardItem
        this.cardsContent.removeAllChildren()

        for (let i = 0; i < Mahjong.TotalCount; i++) {

            let cloneCardItem = cc.instantiate(this.cardItem)

            cloneCardItem.width = cloneCardItem.width * this._gameInfo.cardScale

            cloneCardItem.height = cloneCardItem.height * this._gameInfo.cardScale

            cloneCardItem.idx = i

            this._gameInfo.data.push(`${Mahjong.Type[Math.floor(i / (Mahjong.SingleRepeat * Mahjong.SingleCount))]}${i % Mahjong.SingleCount + 1}`)

            cloneCardItem.parent = this.cardsContent
        }

    }

    onEnable() {

        // 初始化数据
        this._gameInfo.status = GAME_STATUS.INIT

        this._gameInfo.playing = false

        this._gameInfo.totalTime = 0

        this._gameInfo.selectCards = []

        this.timer.getComponent(cc.Label).string = `0s`

        this.shuffle()

        this.setupCards()

        this.hideCards()

        this.startCountdownAnim(SatrtCountdownSecond)

    }

    onDisable() {

        // 重置游戏状态
        this._gameInfo.status = GAME_STATUS.INIT

        // 取消计时
        this.endTiming()

        // 删除选中节点动画
        while (this._gameInfo.selectCards.length) {
            this.endCardAction(this._gameInfo.selectCards.pop())
        }

    }

    hideCards() {

        for (let i = 0; i < this.cardsContent.children.length; i++) {

            let cardItem = this.cardsContent.children[i]

            cardItem.PathChild('cardHide').active = true

            cardItem.PathChild('cardHide').opacity = 255

            cardItem.PathChild('cardShow').active = false

            cardItem.PathChild('cardShow').opacity = 255
        }

    }

    showCards() {

        this._gameInfo.playing = true

        let delayTime = 0

        for (let i = 0; i < this.cardsContent.children.length; i++) {

            let cardItem = this.cardsContent.children[i]

            let hide = cardItem.PathChild('cardHide')

            hide.opacity = 255

            hide.active = true

            let show = cardItem.PathChild('cardShow')

            show.opacity = 0

            show.active = true

            cc.tween(cardItem)
                .delay(delayTime)
                .call(() => {
                    cc.tween(hide).to(0.5, { opacity: 0 }).start()
                    cc.tween(show).to(0.5, { opacity: 255 }).start()
                })
                .delay(0.5)
                .call(() => {
                    if (i >= this.cardsContent.children.length - 1) {
                        this._gameInfo.playing = false
                    }
                })
                .start()

            if (i != 0 && i % LineCount == LineCount - 1) { delayTime += 0.1 }
        }

    }

    shuffle() {

        for (var i = 0; i < this._gameInfo.data.length; i++) {

            let r = ut.RandomInt(0, this._gameInfo.data.length)

            if (i != r) {
                let v = ut.Clone(this._gameInfo.data[i])

                this._gameInfo.data[i] = this._gameInfo.data[r]

                this._gameInfo.data[r] = v
            }
        }

    }

    setupCards() {

        // 数据出现问题
        if (this.cardsContent.children.length != this._gameInfo.data.length) { return cc.error('数据异常') }

        for (let i = 0; i < this.cardsContent.children.length; i++) {

            this.setupCard(i)

        }

    }

    setupCard(idx) {

        let cardItem: any = this.cardsContent.children[idx]

        cardItem.idx = idx

        cardItem.val = this._gameInfo.data[idx]

        cardItem.opacity = cardItem.val == null ? 0 : 255

        if (cardItem.val) {

            ut.SetSpriteFrame(`val/${cardItem.val}`, cardItem.PathChild('cardShow/val', cc.Sprite))

        }

    }

    startCountdownAnim(second) {

        if (this._gameInfo.status != GAME_STATUS.INIT) { return }

        if (second < 0) {

            this.startCountdown.getComponent(cc.Label).string = ''

            this._gameInfo.status = GAME_STATUS.RUNNING

            this._gameInfo.playing = false

            this.startTiming()

            this.showCards()
            return
        }

        let self = this

        this._gameInfo.playing = true

        cc.tween(this.startCountdown)
            .call(() => { self.startCountdown.getComponent(cc.Label).string = `${second}` })
            .to(0.2, { scale: 1.1 })
            .to(0.1, { scale: 1 })
            .delay(0.7)
            .call(() => { self.startCountdownAnim(--second) })
            .start()

    }

    startCardAction(cardItem) {

        cardItem.stopAllActions()

        cardItem.opacity = 255

        cc.tween(cardItem)
            .repeatForever(cc.sequence(cc.fadeOut(0.5), cc.fadeIn(0.5)))
            .start()

    }

    endCardAction(cardItem) {

        cardItem.stopAllActions()

        cardItem.opacity = 255

    }

    errorCardAction(cardItems) {

        for (var i = 0; i < cardItems.length; i++) {

            let node = cardItems[i].PathChild('cardShow')

            node.stopAllActions()

            node.opacity = 255

            cc.tween(node)
                .repeat(3, cc.sequence(cc.moveBy(0.1, -3, 0), cc.moveBy(0.1, 3, 0)))
                .start()
        }
    }

    startTiming() {

        this.schedule(this.tt, 1)

    }

    endTiming() {

        this.unschedule(this.tt)

    }

    check() {

    }

    btnCardItem(e) {

        let curIdx = e.target.idx

        // 已经消除
        if (this._gameInfo.data[curIdx] == null) {

            return

        }

        // 一个都没选中 直接播放选中动画
        let curCardItem: cc.Node = this.cardsContent.children[curIdx]

        if (this._gameInfo.selectCards.length == 0) {

            this._gameInfo.selectCards.push(curCardItem)

            this.startCardAction(curCardItem)

            return
        }

        let lastCardItem = this._gameInfo.selectCards[0]

        let lastIdx = lastCardItem.idx

        // 先把第一个动画停下来
        this.endCardAction(lastCardItem)

        // 选中同一个
        if (this._gameInfo.selectCards.indexOf(curCardItem) != -1) {

            this._gameInfo.selectCards = []

            return                                                                                                       

        }

        // 选择了不一样的两个
        if (lastCardItem.val == curCardItem.val) {

            this._gameInfo.selectCards = []

            this._gameInfo.data[curIdx] = null

            this._gameInfo.data[lastIdx] = null

            this.setupCards()

        } else {

            this._gameInfo.selectCards = []

            this.errorCardAction([lastCardItem, curCardItem])

        }
    }

    btnReturn() {

        if (this._gameInfo.playing) { return }

        this.node.active = false

    }
}